package com.lvcoding.codegen.service.impl;

import cn.hutool.core.util.StrUtil;
import com.lvcoding.codegen.domain.ColumnClass;
import com.lvcoding.codegen.domain.Res;
import com.lvcoding.codegen.domain.TableClass;
import com.lvcoding.codegen.service.GenerateService;
import com.lvcoding.codegen.utils.DbUtil;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Service;

import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Description 描述
 * @Date 2020-12-30 6:01 下午
 * @Author wuyanshen
 */
@Service
public class GenerateServiceImpl implements GenerateService {

    private Configuration cfg = null;
    {
        cfg = new Configuration(Configuration.VERSION_2_3_30);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateLoader(new ClassTemplateLoader(GenerateServiceImpl.class,"/templates"));
    }

    @Override
    public Res generateCode(List<TableClass> tableClassList, String realPath) {
        Set<String> types = new HashSet<>();
        try {
            Template domainTemplate = cfg.getTemplate("Domain.java.ftl");
            Template mapperTemplate = cfg.getTemplate("Mapper.xml.ftl");
            Template mapperXmlTemplate = cfg.getTemplate("Mapper.java.ftl");
            Template serviceTemplate = cfg.getTemplate("Service.java.ftl");
            Template controllerTemplate = cfg.getTemplate("Controller.java.ftl");
            Connection connection = DbUtil.getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            for (TableClass tableClass : tableClassList) {
                ResultSet columns = metaData.getColumns(connection.getCatalog(), null, tableClass.getTableName(), null);
                ResultSet primaryKeys = metaData.getPrimaryKeys(connection.getCatalog(), null, tableClass.getTableName());
                List<ColumnClass> columnClassList = new ArrayList<>();
                while (columns.next()) {
                    String columnName = columns.getString("COLUMN_NAME");
                    String typeName = columns.getString("TYPE_NAME");
                    String remarks = columns.getString("REMARKS");
                    typeName = typeName.contains("UNSIGNED") ? typeName.split(" ")[0] : typeName;

                    ColumnClass columnClass = new ColumnClass();
                    columnClass.setColumnName(columnName);
                    columnClass.setRemark(remarks);
                    columnClass.setPropertyName(StrUtil.toCamelCase(columnName));
                    columnClass.setType(typeName);

                    while (primaryKeys.next()) {
                        String pkName = primaryKeys.getString("COLUMN_NAME");
                        if(columnName.equals(pkName)) {
                            columnClass.setIsPrimary(true);
                        }
                    }

                    types.add(typeName);
                    columnClassList.add(columnClass);
                }
                tableClass.setColumns(columnClassList);
                String path = realPath + "/" + tableClass.getPackageName().replace(".", "/");
                generate(domainTemplate, tableClass,path + "/domain/");
                generate(mapperTemplate, tableClass,path + "/mapper/");
                generate(mapperXmlTemplate, tableClass,path + "/mapper/");
                generate(serviceTemplate, tableClass,path + "/service/");
                generate(controllerTemplate, tableClass,path + "/controller/");
            }
            System.out.println("所有字段的数据库类型：" + types.toString());
            return Res.success("代码已生成", realPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Res.fail("代码生成失败");
    }

    private void generate(Template template, TableClass tableClass, String path) throws IOException, TemplateException {
        File folder = new File(path);
        if(!folder.exists()) {
            folder.mkdirs();
        }
        String fileName = path + "/" + tableClass.getDomainName() + template.getName().replace(".ftl", "").replace("Domain", "");
        FileOutputStream fos = new FileOutputStream(fileName);
        OutputStreamWriter out = new OutputStreamWriter(fos);
        template.process(tableClass, out);

        fos.close();
        out.close();
    }
}
